import os
import time
import zipfile
import json
import shutil
import base64
import tempfile
from pathlib import Path

from PySide6.QtCore import Slot, QUrl
from PySide6.QtWebEngineCore import QWebEngineSettings

from ...utils.base_webview_bridge import BaseWebViewBridge


class Entrance(BaseWebViewBridge):
    """Webview桥接类，用于处理前端和Python后端之间的通信"""

    def __init__(self, webview, parent=None):
        super().__init__(webview, parent)
        self.webview = webview

        # 启用本地文件访问
        self.webview.settings().setAttribute(
            QWebEngineSettings.WebAttribute.LocalContentCanAccessFileUrls, True
        )
        self.webview.settings().setAttribute(
            QWebEngineSettings.WebAttribute.LocalContentCanAccessRemoteUrls, True
        )
        self.webview.settings().setAttribute(
            QWebEngineSettings.WebAttribute.AllowRunningInsecureContent, True
        )
        self.webview.settings().setAttribute(
            QWebEngineSettings.WebAttribute.AllowGeolocationOnInsecureOrigins, True
        )

        # 设置Web安全策略
        self.webview.page().settings().setAttribute(
            QWebEngineSettings.WebAttribute.LocalContentCanAccessFileUrls, True
        )
        self.webview.page().settings().setAttribute(
            QWebEngineSettings.WebAttribute.LocalContentCanAccessRemoteUrls, True
        )
        self.webview.page().settings().setAttribute(
            QWebEngineSettings.WebAttribute.AllowRunningInsecureContent, True
        )

        # 创建插件目录
        self.plugins_dir = Path("plugins")
        os.makedirs(self.plugins_dir, exist_ok=True)

        # 插件信息文件
        self.plugins_info_file = self.plugins_dir / "plugins.json"
        if not self.plugins_info_file.exists():
            with open(self.plugins_info_file, "w") as f:
                json.dump([], f)

    @Slot(str, str, str, result=str)
    def upload_plugin(self, name, description, file_content):
        """处理插件上传请求"""
        try:
            # 将base64编码的文件内容解码并保存为临时文件
            file_data = base64.b64decode(file_content)

            # 创建临时文件来保存上传的ZIP文件
            with tempfile.NamedTemporaryFile(suffix=".zip", delete=False) as tmp_file:
                tmp_file.write(file_data)
                tmp_file_path = tmp_file.name

            # 判断插件是否已存在
            if os.path.exists(self.plugins_dir / name):
                os.unlink(tmp_file_path)
                return json.dumps({"success": False, "error": "插件名称已存在"})

            # 解压插件
            success, msg = self.extract_plugin(tmp_file_path, name)

            if not success:
                # 清理临时文件
                os.unlink(tmp_file_path)
                return json.dumps({"success": False, "error": msg})

            # 读取 plugin.config.json 文件
            plugin_config_file = msg.replace("index.html", "plugin.config.json")
            if not os.path.exists(plugin_config_file):
                os.unlink(tmp_file_path)
                return json.dumps({"success": False, "error": "插件配置文件不存在"})

            with open(plugin_config_file, "r") as f:
                plugin_config = json.load(f)

            plugin_conofig_keys = [
                "pluginName",
                "pluginId",
                "pluginDescription",
                "pluginVersion",
                "pluginAuthor",
            ]

            for key in plugin_conofig_keys:
                if key not in plugin_config:
                    os.unlink(tmp_file_path)
                    return json.dumps(
                        {"success": False, "error": "插件配置文件缺少必要字段"}
                    )

            plugin_info = {
                "id": plugin_config["pluginId"],
                "name": name,
                "pluginName": plugin_config["pluginName"],
                "description": description,
                "version": plugin_config["pluginVersion"],
                "author": plugin_config["pluginAuthor"],
                "uploadDate": time.strftime("%Y-%m-%d", time.localtime()),
                "path": str(self.plugins_dir / name / plugin_config["pluginVersion"]),
            }

            # 创建版本路径并移动插件文件
            version_path = self.plugins_dir / name / plugin_info["version"]
            version_path.mkdir(exist_ok=True)
            for file in os.listdir(os.path.dirname(msg)):
                shutil.move(os.path.join(os.path.dirname(msg), file), version_path)

            # 读取现有插件信息
            if os.path.exists(self.plugins_info_file):
                with open(self.plugins_info_file, "r") as f:
                    plugins = json.load(f)
            else:
                plugins = []

            # 判断pluginId是否存在
            if plugin_info["id"] in [p["id"] for p in plugins]:
                os.unlink(tmp_file_path)
                return json.dumps({"success": False, "error": "插件ID已存在"})

            # 添加新插件
            plugins.append(plugin_info)

            # 保存插件信息
            with open(self.plugins_info_file, "w") as f:
                json.dump(plugins, f)

            # 清理临时文件
            os.unlink(tmp_file_path)

            return json.dumps({"success": True})
        except Exception as e:
            # 确保任何异常都返回有效的JSON
            return json.dumps({"success": False, "error": str(e)})

    @Slot(str, result=str)
    def update_plugin(self, plugin_id, name, description, file_content):
        """处理插件更新请求"""
        try:
            file_data = base64.b64decode(file_content)

            with tempfile.NamedTemporaryFile(suffix=".zip", delete=False) as tmp_file:
                tmp_file.write(file_data)
                tmp_filepath = tmp_file.name

            success, msg = self.extract_plugin(tmp_filepath, name)

            if not success:
                os.unlink(tmp_filepath)
                return json.dumps({"success": False, "error": msg})

            plugin_config_file = msg.replace("index.html", "plugin.config.json")
            if not os.path.exists(plugin_config_file):
                os.unlink(tmp_filepath)
                return json.dumps({"success": False, "error": "插件配置文件不存在"})

            with open(plugin_config_file, "r") as f:
                plugin_config = json.load(f)

            plugin_config_keys = [
                "pluginName",
                "pluginId",
                "pluginDescription",
                "pluginVersion",
                "pluginAuthor",
            ]

            for key in plugin_config_keys:
                if key not in plugin_config:
                    os.unlink(tmp_filepath)
                    return json.dumps(
                        {"success": False, "error": "插件配置文件缺少必要字段"}
                    )

            # 判断插件是否存在
            if not os.path.exists(self.plugins_dir / name):
                os.unlink(tmp_filepath)
                return json.dumps({"success": False, "error": "插件不存在"})

            # 判断版本是否已存在
            version_path = self.plugins_dir / name / plugin_config["pluginVersion"]
            if version_path.exists():
                os.unlink(tmp_filepath)
                return json.dumps({"success": False, "error": "版本已存在"})

            # 创建版本路径并移动插件文件
            version_path.mkdir(exist_ok=True)
            for file in os.listdir(os.path.dirname(msg)):
                shutil.move(os.path.join(os.path.dirname(msg), file), version_path)

            # 更新插件信息
            with open(self.plugins_info_file, "r") as f:
                plugins = json.load(f)

            plugin_info = next((p for p in plugins if p["id"] == plugin_id), None)
            if plugin_info:
                plugin_info["name"] = name
                plugin_info["description"] = description
                plugin_info["version"] = [
                    p["version"] for p in plugins if p["id"] == plugin_id
                ][0]
                plugin_info["uploadDate"] = time.strftime("%Y-%m-%d", time.localtime())
                plugin_info["path"] = str(
                    self.plugins_dir / name / plugin_config["pluginVersion"]
                )

            # 保存插件信息
            with open(self.plugins_info_file, "w") as f:
                json.dump(plugins, f)

            # 清理临时文件
            os.unlink(tmp_filepath)

            return json.dumps({"success": True})
        except Exception as e:
            # 确保任何异常都返回有效的JSON
            return json.dumps({"success": False, "error": str(e)})

    # 解压插件
    def extract_plugin(self, plugin_file, plugin_name):
        """解压插件"""
        try:
            with zipfile.ZipFile(plugin_file, "r") as zf:
                # 获取插件名称
                plugin_dir = self.plugins_dir / plugin_name

                # 如果插件目录已存在，删除
                if plugin_dir.exists():
                    shutil.rmtree(plugin_dir)

                # 创建插件目录并解压
                plugin_dir.mkdir(exist_ok=True)
                zf.extractall(plugin_dir)

                # 检测是否有 index.html 文件
                index_file = plugin_dir / "index.html"
                if not index_file.exists():
                    # 查找任何HTML文件作为入口
                    html_files = list(plugin_dir.glob("*.html"))
                    if not html_files:
                        return False, "插件中未找到HTML文件"
                    index_file = html_files[0]

                return True, str(index_file.absolute())
        except Exception as e:
            return False, str(e)

    @Slot(result=str)
    def list_plugins(self):
        """获取插件列表"""
        try:
            if os.path.exists(self.plugins_info_file):
                with open(self.plugins_info_file, "r") as f:
                    plugins = json.load(f)
                return json.dumps({"success": True, "plugins": plugins})
            else:
                return json.dumps({"success": True, "plugins": []})
        except Exception as e:
            # 确保任何异常都返回有效的JSON
            return json.dumps({"success": False, "error": str(e)})

    @Slot(str, result=str)
    def launch_plugin(self, plugin_id):
        """启动插件"""
        try:
            if os.path.exists(self.plugins_info_file):
                with open(self.plugins_info_file, "r") as f:
                    plugins = json.load(f)

                # 查找插件
                plugin = next((p for p in plugins if p["id"] == plugin_id), None)
                print(f"Launching plugin: {plugin}")
                if plugin:
                    # 构建插件URL
                    plugin_path = Path(plugin["path"])
                    # 查找HTML文件作为入口
                    html_files = list(plugin_path.glob("*.html"))
                    if html_files:
                        index_file = html_files[0]
                        url = QUrl.fromLocalFile(str(index_file.absolute()))
                        print(f"Launching plugin: {url.toString()}")
                        print(f"Plugin path: {plugin_path}")
                        self.webview.load(url)
                        return json.dumps({"success": True, "url": url.toString()})
                    else:
                        return json.dumps(
                            {"success": False, "error": "插件入口文件未找到"}
                        )
                else:
                    return json.dumps({"success": False, "error": "插件未找到"})
            else:
                return json.dumps({"success": False, "error": "插件信息文件未找到"})
        except Exception as e:
            # 确保任何异常都返回有效的JSON
            return json.dumps({"success": False, "error": str(e)})

    @Slot(str, result=str)
    def save_settings(self, settings_json):
        """保存设置"""
        try:
            settings = json.loads(settings_json)
            # 在实际应用中，这里会保存设置到配置文件
            print(f"保存设置: {settings}")
            return json.dumps({"success": True})
        except Exception as e:
            # 确保任何异常都返回有效的JSON
            return json.dumps({"success": False, "error": str(e)})
